#ifndef _SCRIPTENGINE_H_
#define _SCRIPTENGINE_H_

#include <sol/sol.hpp>
#include <functional>
#include <string>

namespace Engine2D
{
    class Scene;

    class ScriptEngine
    {
    public:
        static ScriptEngine& Instance();
        sol::state & State() { return s_lua; }
        void SetActiveScene(std::shared_ptr<Scene> scene) { m_activeScene = scene; }
        std::shared_ptr<Scene> ActiveScene() { return m_activeScene.lock(); }
        void SetErrorCallback(std::function<void(const std::string &)> && fn) { m_scriptErrorCb = std::move(fn); }
        void Script(const std::string & src);
        template<typename T>
        static void RegisterUserType();
    private:
        ScriptEngine();
        virtual ~ScriptEngine() = default;
        inline static sol::state s_lua;
        std::weak_ptr<Scene> m_activeScene;
        std::function<void(const std::string &)> m_scriptErrorCb;
    };
    
    template<typename T>
    inline void ScriptEngine::RegisterUserType()
    {
        Reflect<T> info;
        sol::usertype<T> type = ScriptEngine::Instance().State().new_usertype<T>(info.Name());
        info.Foreach([&type](auto field) {
            type[field.name] = field.ptr;
        });
    }
} // namespace Engine2D

#endif